package com.nulldev.util.java.swing.fastEPane;

import java.io.IOException;
import java.io.StringReader;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;

import javax.swing.text.BadLocationException;
import javax.swing.text.ViewFactory;
import javax.swing.text.html.HTML;
import javax.swing.text.html.HTMLDocument;
import javax.swing.text.html.HTMLEditorKit;

import com.nulldev.util.logging.Logger;
import com.nulldev.util.logging.LoggerFactory;
import com.nulldev.util.threading.legacy.ThreadExecutor;
import com.nulldev.util.threading.v2.SafeRunnable;
import com.nulldev.util.threading.v2.ThreadExecution;
import com.nulldev.util.threading.v2.ThreadManager;
import com.nulldev.util.threading.v2.ThreadMode;
import com.nulldev.util.threading.v2.ThreadPriority;
import com.nulldev.util.threading.v2.nThread;

public class FastEditorKit extends HTMLEditorKit  {
	
	private final Logger log = LoggerFactory.getLogger();
	private final ThreadManager tm = new ThreadManager();
	//private final v3TManager tm3 = new v3TManager(true);

	public final FastViewFactory fvf = new FastViewFactory();
    final ViewFactory factory = fvf;
    
    public FastEditorKit() {
    	super();
    	//tm3.setDelay(50L);
    }
    
    public ViewFactory getViewFactory() {
        return factory;
    }
    
    public FastViewFactory getViewFactory_Parsed() {
    	return this.fvf;
    }
    
    /**
     * Inserts HTML into an existing document.
     *
     * @param doc       the document to insert into
     * @param offset    the offset to insert HTML at
     * @param popDepth  the number of ElementSpec.EndTagTypes to generate before
     *        inserting
     * @param pushDepth the number of ElementSpec.StartTagTypes with a direction
     *        of ElementSpec.JoinNextDirection that should be generated
     *        before inserting, but after the end tags have been generated
     * @param insertTag the first tag to start inserting into document
     * @exception RuntimeException (will eventually be a BadLocationException)
     *            if pos is invalid
     */
    @Override
    public void insertHTML(HTMLDocument doc, int offset, String html,
                           int popDepth, int pushDepth,
                           HTML.Tag insertTag) throws
                       BadLocationException, IOException {
        if (offset > doc.getLength()) {
            throw new BadLocationException("Invalid location", offset);
        }
        
		try {
			final StringReader sr = new StringReader(html);
			Parser p = ensureParser(doc);
			ParserCallback receiver = doc.getReader(offset, popDepth, pushDepth,
                                                insertTag);
			Boolean ignoreCharset = (Boolean)doc.getProperty
                                ("IgnoreCharsetDirective");
			p.parse(sr, receiver, (ignoreCharset == null) ?
                false : ignoreCharset.booleanValue());
			try {
				receiver.flush();
			}catch (Exception e) {}
			sr.close();
		}catch (Exception e) {
			e.printStackTrace();
		}

//        ThreadExecutor.execute(new SafeRunnable() {
//			
//        	@Override
//			public void run() {
//				try {
//					final StringReader sr = new StringReader(html);
//			        Parser p = ensureParser(doc);
//			        ParserCallback receiver = doc.getReader(offset, popDepth, pushDepth,
//			                                                insertTag);
//			        Boolean ignoreCharset = (Boolean)doc.getProperty
//			                                ("IgnoreCharsetDirective");
//			        p.parse(sr, receiver, (ignoreCharset == null) ?
//			                false : ignoreCharset.booleanValue());
//			        receiver.flush();
//			        sr.close();
//				}catch (Exception e) {
//					this.onException(e);
//				}
//			}
//
//			@Override
//			public void onException(final Throwable t) {
//				log.error("Failed to insert element!", t);
//			}
//		});
//        tm.addTask(new nThread(new SafeRunnable() {
//			
//        	@Override
//			public void run() {
//				try {
//			        final Parser p = ensureParser(doc);
//			        final ParserCallback receiver = doc.getReader(offset, popDepth, pushDepth,
//			                                                insertTag);
//			        final Boolean ignoreCharset = (Boolean)doc.getProperty
//			                                ("IgnoreCharsetDirective");
//			        p.parse(new StringReader(html), receiver, (ignoreCharset == null) ?
//			                false : ignoreCharset.booleanValue());
//			        receiver.flush();
//				}catch (Exception e) {
//					this.onException(e);
//				}
//			}
//
//			@Override
//			public void onException(final Throwable t) {
//				//log.error("Failed to insert element!", t);
//			}
//		}, "$fastek.addItem", ThreadPriority.NORMAL, ThreadExecution.NORMAL, ThreadMode.NORMAL));
//        this.tm3.addThread(new v3Thread(new Runnable() {
//			
//			@Override
//			public void run() {
//				try {
//					final StringReader sr = new StringReader(html);
//					Parser p = ensureParser(doc);
//					ParserCallback receiver = doc.getReader(offset, popDepth, pushDepth,
//		                                                insertTag);
//					Boolean ignoreCharset = (Boolean)doc.getProperty
//		                                ("IgnoreCharsetDirective");
//					p.parse(sr, receiver, (ignoreCharset == null) ?
//		                false : ignoreCharset.booleanValue());
//					receiver.flush();
//					sr.close();
//				}catch (Exception e) {
//					e.printStackTrace();
//				}
//			}
//		}));
    }
    
    /**
     * Try to get an HTML parser from the document.  If no parser is set for
     * the document, return the editor kit's default parser.  It is an error
     * if no parser could be obtained from the editor kit.
     */
    private Parser ensureParser(HTMLDocument doc) throws IOException {
        Parser p = doc.getParser();
        if (p == null) {
            p = getParser();
        }
        if (p == null) {
            throw new IOException("Can't load parser");
        }
        return p;
    }
	
}
